/****************************************\
|* MFZPSP LLE PSP Emulator              *|
|* Copyright (c) 2008 Mauro Frischherz  *|
|* See License.txt for details          *|
\****************************************/

//start 		    end 	  size 	description
//-----------|------------|------|-----------------------------------
//0x00010000 | 0x00013fff | 16kb | scratchpad
//0x04000000 | 0x041fffff | 2mb  | Video Memory / Frame Buffer
//0x08000000 | 0x09ffffff | 32mb | Main Memory
//0x1c000000 | 0x1fbfffff | 	 | Hardware i/o
//0x1fc00000 | 0x1fcfffff | 1mb  | Hardware Exception Vectors (RAM)
//0x1fd00000 | 0x1fffffff |  	 | Hardware i/o
//-------------------yet another PlayStationPortable Documentation---

#include "memory.h"
#include <malloc.h>

#include "../tools/log.h"

inline void* GetPadd(uint Address);
void		 FreeMemory();
void		 InitMemory();

ubyte* mmem;
ubyte* vidm;
ubyte* scrp;
ubyte* zero;

uint mmem_base = 0x08000000;
uint vidm_base = 0x04000000;
uint scrp_base = 0x00010000;

uint mmem_mask = 0x01FFFFFF;
uint vidm_mask = 0x001FFFFF;
uint scrp_mask = 0x00003FFF;

bool initialised = false;


void ResetMemory()
{
	FreeMemory();
	InitMemory();
}
void FreeMemory()
{
	if(initialised)
	{
		free(mmem);
		free(vidm);
		free(scrp);
		free(zero);
		initialised = false;
	}
}

void InitMemory()
{
	if(!initialised)
	{
		mmem = (ubyte*) calloc(0x01FFFFFF, sizeof(ubyte));
		vidm = (ubyte*) calloc(0x001FFFFF, sizeof(ubyte));
		scrp = (ubyte*) calloc(0x00003FFF, sizeof(ubyte));
		zero = (ubyte*) calloc(0x0000000F, sizeof(ubyte));
		initialised = true;
	}
}

inline char	 Read8(uint Address) 	{ char* pret 	= (char*)GetPadd(Address); 	 return *pret; }
inline short Read16(uint Address) 	{ short* pret 	= (short*)GetPadd(Address);	 return *pret; }
inline int   Read32(uint Address) 	{ int* pret 	= (int*)GetPadd(Address); 	 return *pret; }

inline ubyte  uRead8(uint Address) 	{ ubyte* pret 	= (ubyte*)GetPadd(Address);  return *pret; }
inline ushort uRead16(uint Address) { ushort* pret 	= (ushort*)GetPadd(Address); return *pret; }
inline uint	  uRead32(uint Address) { uint *pret 	= (uint*)GetPadd(Address);   return *pret; }


inline void Write8(uint Address, char Value) 	 { char* ptar 	= (char*)GetPadd(Address); 	 *ptar = Value; }
inline void	Write16(uint Address, short Value) 	 { short* ptar 	= (short*)GetPadd(Address);  *ptar = Value; }
inline void Write32(uint Address, int Value)	 { int* ptar 	= (int*)GetPadd(Address); 	 *ptar = Value; }

inline void uWrite8(uint Address, ubyte Value)   { ubyte* ptar	= (ubyte*)GetPadd(Address);  *ptar = Value; }
inline void	uWrite16(uint Address, ushort Value) { ushort* ptar = (ushort*)GetPadd(Address); *ptar = Value; }
inline void uWrite32(uint Address, uint Value)	 { uint* ptar	= (uint*)GetPadd(Address);	 *ptar = Value; }

void WriteLarge(uint Address, ubyte* Input, uint Size)
{
	uint i;
	for(i = 0; i < Size; i++)
	{
		ubyte* ptar = (ubyte*)GetPadd(Address + i);
		*ptar = Input[i];
	}
}

void ZeroMem(uint Address, uint Size)
{
	uint i;
	for(i = 0; i < Size; i++)
	{
		ubyte* ptar = (ubyte*)GetPadd(Address + i);
		*ptar = 0;
	}
}


void* GetPadd(uint Address)
{
	switch(Address >> 24)
	{
	case 0x08:
		return &mmem[Address & mmem_mask];
		break;
	case 0x04:
		return &vidm[Address & vidm_mask];
		break;
	case 0x00:
		return &scrp[Address & scrp_mask];
		break;
	default:
		return &zero[0];
		break;
	}
	return 0;
}

bool GetMemInitialised()
{
	return initialised;
}

